<!DOCTYPE html>
<html >
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    
    <title>回车、换行、和文件末尾空行 | Eggward_Han</title>
    <meta name="renderer" content="webkit">
    <meta name="HandheldFriendly" content="True">
    <meta name="MobileOptimized" content="320">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <meta name="description" content="回车和换行在不同系统下面定义不同，时不时会有一些小问题出来，git 经常出现的 No new line at the end of file 也让很多人费解，需要梳理一下">

    <meta name="twitter:card" content="summary">
    <meta name="twitter:title" content="回车、换行、和文件末尾空行 | Eggward_Han">
    <meta name="twitter:description" content="回车和换行在不同系统下面定义不同，时不时会有一些小问题出来，git 经常出现的 No new line at the end of file 也让很多人费解，需要梳理一下">

    <meta property="og:type" content="article">
    <meta property="og:title" content="回车、换行、和文件末尾空行 | Eggward_Han">
    <meta property="og:description" content="回车和换行在不同系统下面定义不同，时不时会有一些小问题出来，git 经常出现的 No new line at the end of file 也让很多人费解，需要梳理一下">

    
    <meta name="author" content="Eggward">
    
    <link rel="stylesheet" href="/css/vno.css">
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css">

    
    <link rel="icon" href="/images/favicon.ico">
    

    <meta name="generator" content="hexo"/>
    
    <link rel="alternate" type="application/rss+xml" title="Eggward_Han" href="/atom.xml">
    

    <link rel="canonical" href="http://www.eggwardhan.com/2018/01/24/2018-01-01-carriage-return-line-feed-new-line-end-file/"/>

                 
</head>

<body class="home-template no-js">
    <script src="//cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
    <script src="/js/main.js"></script>
    <span class="mobile btn-mobile-menu">
        <i class="fa fa-list btn-mobile-menu__icon"></i>
        <i class="fa fa-angle-up btn-mobile-close__icon hidden"></i>
    </span>

    
<header class="panel-cover panel-cover--collapsed" style="background-image: url(/images/background-cover.jpg)">
  <div class="panel-main">
    <div class="panel-main__inner panel-inverted">
    <div class="panel-main__content">

        <a href="/" title="前往 Eggward_Han 的主页"><img src="/images/favicon.ico" width="80" alt="Eggward_Han logo" class="panel-cover__logo logo" /></a>
        <h1 class="panel-cover__title panel-title"><a href="/" title="link to homepage for Eggward_Han">Eggward_Han</a></h1>
        
        <span class="panel-cover__subtitle panel-subtitle">爱玩儿的码农</span>
        
        <hr class="panel-cover__divider" />
        <p class="panel-cover__description">一个阴暗的小角落</p>
        <hr class="panel-cover__divider panel-cover__divider--secondary" />

        <div class="navigation-wrapper">
          <div>
          <nav class="cover-navigation cover-navigation--primary">
            <ul class="navigation">
              <li class="navigation__item"><a href="/#blog" title="Visit the blog" class="blog-button">Blog</a></li>
            
              <li class="navigation__item"><a href="/favourite">黄金屋</a></li>
            
              <li class="navigation__item"><a href="/favourite/time.html">时光机</a></li>
            
              <li class="navigation__item"><a href="/favourite/image.html">幻想间</a></li>
            
              <li class="navigation__item"><a href="/aboutme">关于我</a></li>
            
            </ul>
          </nav>
          </div>
          <div>
          <nav class="cover-navigation navigation--social">
  <ul class="navigation">

  <!-- Weibo-->
  

  <!-- Github -->
  
  <li class="navigation__item">
    <a href="https://github.com/Eggwardhan" title="GitHub" target="_blank">
      <i class='social fa fa-github'></i>
      <span class="label">Github</span>
    </a>
  </li>


<!-- Stack Overflow -->
        

  <!-- Google Plus -->
  

<!-- Facebook -->

  
<!-- Twitter -->

  <li class="navigation__item">
    <a href="https://twitter.com/eggwardhan" title="Twitter" target="_blank">
      <i class='social fa fa-twitter'></i>
      <span class="label">Twitter</span>
    </a>
  </li>

  

  <li class="navigation__item">
    <a href="/atom.xml" title="RSS" target="_blank">
      <i class='social fa fa-rss'></i>
      <span class="label">RSS</span>
    </a>
  </li>



  </ul>
</nav>

          </div>
        </div>

      </div>

    </div>

    <div class="panel-cover--overlay cover-purple"></div>
  </div> 
</header>

    <div class="content-wrapper">
        <div class="content-wrapper__inner">
            <article class="post-container post-container--single">

  <header class="post-header">
    <div class="post-meta">
      <time datetime="2018-01-24T12:58:22.869Z" class="post-list__meta--date date">2018-01-24</time> &#8226; <span class="post-meta__tags tags">于  </span>
      <span class="page-pv">
       Read <span id="busuanzi_value_page_pv"><i class="fa fa-spinner fa-spin"></i></span>
      </span> 
   
    </div>
    <h1 class="post-title">回车、换行、和文件末尾空行</h1>
  </header>

  <section class="post">
    <h2 id="回车和换行"><a href="#回车和换行" class="headerlink" title="回车和换行"></a>回车和换行</h2><p>回车 (Carriage Return) 和换行 (Line Feed) 的区别，<a href="http://stackoverflow.com/questions/1761051/difference-between-n-and-r" target="_blank" rel="noopener">这里</a>有一个历史原因可参考：</p>
<blockquote>
<p>在计算机还没有出现之前，有一种叫做电传打字机（Teletype Model 33）的玩意，每秒钟可以打10个字符。但是它有一个问题，就是打完一行换行的时候，要用去0.2秒，正好可以打两个字符。要是在这0.2秒里面，又有新的字符传过来，那么这个字符将丢失。</p>
<p>于是，研制人员想了个办法解决这个问题，就是在每行后面加两个表示结束的字符。一个叫做”回车”，告诉打字机把打印头定位在左边界；另一个叫做”换行”，告诉打字机把纸向下移一行。</p>
</blockquote>
<p>发明计算机时，这个概念被沿用下来，但因为条件的限制和设计者的喜好，有了一些分歧：</p>
<ul>
<li>Unix 系统里，每行结尾只有”&lt;换行&gt;”，即”\n”</li>
<li>Windows 系统里面，每行结尾是”&lt;回车&gt;&lt;换行&gt;”，即”\r\n”</li>
<li>在老的 Mac 系统里，每行结尾是”&lt;回车&gt;”，即”\r”</li>
</ul>
<p>我们来验证一下，我在 Windows 下用记事本新建一个文本文件，它的二进制编码如下：</p>
<pre><code>//源文件内容
hello
hello2

//二进制内容
0000000: 6865 6c6c 6f0d 0a68 656c 6c6f 32         hello..hello2
</code></pre><p>同样在 Mac 下用 Vim 新建一个：</p>
<pre><code>//源文件内容
hello
hello2

//二进制内容
0000000: 6865 6c6c 6f0a 6865 6c6c 6f32 0a         hello.hello2.
</code></pre><p><code>0a</code>是 LF 的 ASCII 编码, <code>0d</code>是 CR 的 ASCII 编码。区别很明显了</p>
<ul>
<li>Mac 下的文本文件在 Windows 下打开会成为一行，因为 Windows 只认识<code>\r\n</code>，也就是<code>0d0a</code></li>
<li>Windows 下的文本文件在 Mac 下打开，Vim 中会在每行末尾显示一个 <code>^M</code>，(不是两个字符组成的)</li>
</ul>
<h2 id="文件末尾空行"><a href="#文件末尾空行" class="headerlink" title="文件末尾空行"></a>文件末尾空行</h2><p><a href="https://zh.wikipedia.org/zh-sg/POSIX" target="_blank" rel="noopener">POSIX</a>对行的<a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206" target="_blank" rel="noopener">定义</a>如下：</p>
<blockquote>
<p>3.206 Line</p>
<p>A sequence of zero or more non- <newline\> characters plus a terminating <newline\> character.</newline\></newline\></p>
<p>行是由0个或者多个非 “换行” 符的字符组成，并且以 “换行” 符结尾。</p>
</blockquote>
<p>这样做有什么好处呢，举个例子：</p>
<pre><code>//hello.c
#include head.h
print(&apos;hello&apos;)

//world.c
#include tail.h
print(&apos;hello&apos;)
</code></pre><p>如果这两个文件都按 POSIX 规范来写， 在<code>cat *.c</code>之后，是没有问题的：</p>
<pre><code>//cat.c

#include head.h
print(&apos;hello&apos;)
#include tail.h
print(&apos;hello&apos;)
</code></pre><p>如果缺少最后一行的换行符（如 Windows 文件那样的定义），<code>cat</code>之后，就有问题了：</p>
<pre><code>//error.c

#include head.h
print(&apos;hello&apos;)#include tail.h
print(&apos;hello&apos;)
</code></pre><p>所以，从这点去理解 POSIX 对行的定义，非常合理，对于任意文件的拼接，也各自保持了文件的完整性。</p>
<p>不遵守标准带来的则是：在一些编辑器下面，比如 Sublime，他把<code>\n</code>的当做了行之间的分隔符，于是文件最后一行的<code>\n</code>就看上去成了一个新的空行，这就是错误解读标准造成的，拼接文件时也会产生不必要的麻烦，比如上例。</p>
<h2 id="No-new-line-at-end-of-file"><a href="#No-new-line-at-end-of-file" class="headerlink" title="\ No new line at end of file"></a>\ No new line at end of file</h2><p>基于上面的原因，再去看 git diff 的<code>\ No new line at end of file</code>信息，就很好解释了。</p>
<p>各编辑器对于换行符的理解偏差，导致的文件确实发生了变化，多了或少了最后的<code>0a</code>，那么对于 diff 程序来说，这当然是不可忽略的，但因为<code>0a</code>是不可见字符，并且是长久以来的历史原因，所以 diff 程序有个专门的标记来说明这个变化，就是：</p>
<p><code>\ No new line at end of file</code></p>
<p>各编辑器也有相应的办法去解决这个问题，比如 Sublime，在<code>Default/Preferences.sublime-settings</code>中设置：</p>
<pre><code>// Set to true to ensure the last line of the file ends in a newline
// character when saving
&quot;ensure_newline_at_eof_on_save&quot;: true,
</code></pre><p>所以，请遵守规范。</p>

  </section>

</article>

<section class="read-more">
           
    
               
            <div class="read-more-item">
                <span class="read-more-item-dim">Newer Post</span>
                <h2 class="post-list__post-title post-title"><a href="/2018/01/24/2018-01-24-aim/" title="寒假flag">寒假flag</a></h2>
                <p class="excerpt">
                
                  今日立下flag，我将在2018的寒假完成以下的任务:    1 学习python3的基本知识    2 在虚拟机上搭建nginx + uwsgi +django（1.11）的环境    3 在虚拟机上搭建mysql（or MariaDb)    4 跑通django的tutorial    5
                &hellip;
                </p>
                <div class="post-list__meta"><time datetime="2018-01-24T14:18:05.680Z" class="post-list__meta--date date">2018-01-24</time> &#8226; <span class="post-list__meta--tags tags">于 </span><a class="btn-border-small" href="/2018/01/24/2018-01-24-aim/">继续阅读</a></div>
                           
            </div>
        
        
        
     
   
   
  
</section>

  

            <footer class="footer">
    <span class="footer__copyright">
        &copy; 2018 Eggward - 本站点采用 <a href="http://creativecommons.org/licenses/by-nc-sa/4.0/">知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议</a>
       
    </span>
    <span class="footer__copyright">
             - 基于 <a href="http://hexo.io">Hexo</a> 搭建，使用 <a href="https://github.com/monniya/hexo-theme-new-vno ">new-vno</a> 主题，由<a href="https://monniya.com ">@Monniya</a> 修改自 <a href="https://github.com/lenbo-ma/hexo-theme-vno" target="_blank">Vno</a>, 原创出自<a href="http://github.com/onevcat/vno" target="_blank">onevcat</a>
         </span>
       
    
    
</footer>


        </div>
    </div>

     
<script>
	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

	ga('create', 'UA-78918255-1', 'auto');
	ga('send', 'pageview');
</script>

    
    <script>
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "//hm.baidu.com/hm.js?9cdad07c755fa23f6aced510c6760e87";
            var s = document.getElementsByTagName("script")[0]; 
            s.parentNode.insertBefore(hm, s);
        })();
    </script>



    <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    
    
</body>
</html>
